﻿
using MvCamCtrl.NET;
using MvCameraControl;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;
using YJYpublicClass;
using 检测.HKCamera2;
using System.IO;
using System.ComponentModel;
using Cognex.VisionPro;

namespace YJYpublicClass
{
    public class HKCamera2
    {
      
        public string Savepath { get; set; } = "海康相机2.xml";

        [TypeConverter(typeof(ExpandableObjectConverter))]
        [EditorBrowsable(EditorBrowsableState.Always)]
        [Category("相机参数"), Description("string"), DisplayName("配置参数"), ReadOnly(false)]   
        public HKCaConfig config { get; set; }= new HKCaConfig();
        //变量定义
        [XmlIgnore]
        public List<string> reMES { get; set; } = new List<string>();

        [XmlIgnore]
        public double zhenlv { get; set; } = 0;
        [XmlIgnore]
        public double haoshi { get; set; } = 0;
        [XmlIgnore]
        IDevice device = null;
        [XmlIgnore]
        public int CamreOpenFlag { get; set; } = 0;
        [XmlIgnore]
        public Boolean m_bGrabbing { get; set; } = false;
        [XmlIgnore]
        Boolean grabThreadflag = false;
        [XmlIgnore]
        public PictureBox PictureBox1 = null;
        //[XmlIgnore]
        //public IInputOutputArray tempreimg = null;
        [XmlIgnore]
        //public HObject tempreimg_H = new HObject();
        [NonSerialized]
        // CogImage24PlanarColor colorImage;
        public ICogImage OutVisionImage;
    
        [XmlIgnore]
        public static List<string> CameraSnNames = new List<string>();
        [XmlIgnore]
        public static List<IDeviceInfo> devInfoList = new List<IDeviceInfo>();
        [XmlIgnore]
        public Boolean getNewImageFlag = false;
        [XmlIgnore]
        public Action _取图事件 = null;

        public static void camerasysteminit()
        {
            SDKSystem.Initialize();
        }
        //
        public static void camerasystemdistroy()
        {
            SDKSystem.Finalize();
        }

        public HKCamera2()
        { 
        }
        public HKCamera2(string _存储路径)
        {
            Savepath=_存储路径;
        }
        public static void Enumdevlist()
        {
            CameraSnNames.Clear();
            // List<IDeviceInfo> devInfoList = null;
            int ret = DeviceEnumerator.EnumDevices(DeviceTLayerType.MvGigEDevice | DeviceTLayerType.MvUsbDevice | DeviceTLayerType.MvGenTLCXPDevice | DeviceTLayerType.MvGenTLXoFDevice, out devInfoList);
            if (ret != MvError.MV_OK)
            {
                return;
            }
            foreach (IDeviceInfo devInfo in devInfoList)
            {

                // MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(devInfoList.ElementAt(i), typeof(MyCamera.MV_CC_DEVICE_INFO));       
                if (devInfo.TLayerType == DeviceTLayerType.MvGigEDevice)
                {
                    if (devInfo.ModelName.Contains("MV"))
                    {
                        CameraSnNames.Add("GigE: " + devInfo.ModelName + " " + devInfo.UserDefinedName + " (" + devInfo.SerialNumber + ")");
                    }
                    else
                    {
                        CameraSnNames.Add("GigE: " + devInfo.ManufacturerName + " " + devInfo.ModelName + " (" + devInfo.SerialNumber + ")");
                    }
                }
                else if (devInfo.TLayerType == DeviceTLayerType.MvUsbDevice)
                {

                    if (devInfo.ModelName.Contains("MV"))
                    {
                        CameraSnNames.Add("USB: " + devInfo.ModelName + " " + devInfo.UserDefinedName + " (" + devInfo.SerialNumber + ")");
                    }
                    else
                    {
                        CameraSnNames.Add("USB: " + devInfo.ManufacturerName + " " + devInfo.ModelName + " (" + devInfo.SerialNumber + ")");
                    }
                }
            }

        }
        //打开设备
        public void OpenCamera(int index)
        {
            reMES.Clear();
            if (devInfoList.Count == 0)
            {
                Enumdevlist();
            }
            if (devInfoList.Count < index)
            {
                reMES.Add("索引超出范围");
                return;
            }
            try
            {
                /*创建相机实例*/
                device = DeviceFactory.CreateDevice(devInfoList.ElementAt(index));

                ///*打开相机*/
                int ret = device.Open();
                if (ret != MvError.MV_OK)
                {
                    reMES.Add(string.Format("Open device fail: {0}", ret));
                    return;
                }
                /*如果是网口相机*/
                if (device is IGigEDevice)
                {
                    IGigEDevice gigEDevice = device as IGigEDevice;
                    /*配置网口相机的最佳包大小*/
                    int packetSize;
                    gigEDevice.GetOptimalPacketSize(out packetSize);
                    gigEDevice.Parameters.SetIntValue("GevSCPSPacketSize", packetSize);
                }
                else if (device is IUSBDevice)
                {
                    /*设置USB同步读写超时时间*/
                    IUSBDevice usbDevice = device as IUSBDevice;
                    usbDevice.SetSyncTimeOut(1000);
                }
                //
                // int ret = device.Open();

                //ch: 设置合适的缓存节点数量 | en: Setting the appropriate number of image nodes
                device.StreamGrabber.SetImageNodeNum(1);

                // ch:注册回调函数 | en:Register image callback
                device.StreamGrabber.FrameGrabedEvent += FrameGrabedEventHandler;

                //ret = device.StreamGrabber.StartGrabbing();
                //if (ret != MvError.MV_OK)
                //{
                //    Console.WriteLine("Start grabbing failed:{0:x8}", ret);
                //    return;
                //}

                //// ch:开启抓图线程 | en: Start the grabbing thread
                //grabThreadflag=true;
                //Thread GrabThread = new Thread(FrameGrabThread);
                //GrabThread.Start();

                // ch:开启抓图 || en: start grab image

                CamreOpenFlag = 1;

            }
            catch (Exception e)
            {
                reMES.Add("Create device fail" + e.Message);
            }


        }
        //设置触发模式

        public void StartGrab()
        {

            // ch:开启抓图 | en:start grab
            int ret = device.StreamGrabber.StartGrabbing();
            if (ret != MvError.MV_OK)
            {
                Console.WriteLine("Start grabbing failed:{0:x8}", ret);
                return;
            }
            m_bGrabbing = true;
            tw1.Stop();
            i = 0;
        }
        public void StopGrab()
        {
            int nRet = -1;
            // ch:停止抓图 || en:Stop grab image
            nRet = device.StreamGrabber.StopGrabbing();
            if (nRet != MyCamera.MV_OK)
            {
                reMES.Add("Stop Grabbing Fail");
            }
            m_bGrabbing = false;
        }

        Stopwatch tw1 = new Stopwatch();
        Stopwatch tw2 = new Stopwatch();
        int i = 0;
        [XmlIgnore]
        public int tupianindex = 0;
        public int lasttupianindex = -1;

        //回调取图
        void FrameGrabedEventHandler(object sender, FrameGrabbedEventArgs e)
        {

            try
            {
                if (!tw1.IsRunning)
                {
                    tw1.Restart();
                }
                tw2.Restart();
                //device.ImageRender.DisplayOneFrame(PictureBox1.Handle, e.FrameOut.Image);
                //开始转图像
                //MvGvspPixelType dstPixelType = e.FrameOut.Image.PixelType;
                if (IsMonoPixelFormat(e.FrameOut.Image.PixelType))
                {
                    //判断是不是mono8，然后再处理,转成MOMO8
                    if (e.FrameOut.Image.PixelType == MvGvspPixelType.PixelType_Gvsp_Mono8)
                    {
                        //直接转图像
                        //tempreimg = new Image<Gray, byte>((int)e.FrameOut.Image.Width, (int)e.FrameOut.Image.Height, (int)(int)e.FrameOut.Image.Width * 1, e.FrameOut.Image.PixelDataPtr);
                        //HOperatorSet.GenImage1Extern(out tempreimg_H, "byte", (int)e.FrameOut.Image.Width, (int)e.FrameOut.Image.Height, e.FrameOut.Image.PixelDataPtr, 0);
                        Ptr2VisionImge(e.FrameOut.Image.Width, e.FrameOut.Image.Height, e.FrameOut.Image.PixelDataPtr, (MyCamera.MvGvspPixelType)e.FrameOut.Image.PixelType, out OutVisionImage);
                    }
                    else
                    {
                        int result = device.PixelTypeConverter.ConvertPixelType(e.FrameOut.Image, out IImage outImage, MvGvspPixelType.PixelType_Gvsp_Mono8);
                        if (MyCamera.MV_OK != result)
                        {
                            return;
                        }
                        //tempreimg = new Image<Gray, byte>((int)e.FrameOut.Image.Width, (int)e.FrameOut.Image.Height, (int)e.FrameOut.Image.Width * 1, outImage.PixelDataPtr);
                        //HOperatorSet.GenImage1Extern(out tempreimg_H, "byte", (int)e.FrameOut.Image.Width, (int)e.FrameOut.Image.Height, outImage.PixelDataPtr, 0);

                        Ptr2VisionImge(e.FrameOut.Image.Width, e.FrameOut.Image.Height, e.FrameOut.Image.PixelDataPtr, (MyCamera.MvGvspPixelType)e.FrameOut.Image.PixelType, out OutVisionImage);
                    }
                }
                else if (IsColorPixelFormat(e.FrameOut.Image.PixelType))
                {

                    if (e.FrameOut.Image.PixelType == MvGvspPixelType.PixelType_Gvsp_BGR8_Packed)
                    {
                        //tempreimg = new Image<Bgr, byte>((int)e.FrameOut.Image.Width, (int)e.FrameOut.Image.Height, (int)e.FrameOut.Image.Width * 3, e.FrameOut.Image.PixelDataPtr);
                        //HOperatorSet.GenImageInterleaved(out tempreimg_H, e.FrameOut.Image.PixelDataPtr, "bgr", (int)e.FrameOut.Image.Width, (int)e.FrameOut.Image.Height, 0, "byte", 0, 0, 0, 0, -1, 0);
                        Ptr2VisionImge(e.FrameOut.Image.Width, e.FrameOut.Image.Height, e.FrameOut.Image.PixelDataPtr, (MyCamera.MvGvspPixelType)e.FrameOut.Image.PixelType, out OutVisionImage);
                    }
                    else
                    {
                        //nRet = ConvertToRGB(m_MyCamera, pData, pFrameInfo.nHeight, pFrameInfo.nWidth, pFrameInfo.enPixelType, IpData);
                        int result = device.PixelTypeConverter.ConvertPixelType(e.FrameOut.Image, out IImage outImage, MvGvspPixelType.PixelType_Gvsp_BGR8_Packed);
                        if (MyCamera.MV_OK != result)
                        {
                            return;
                        }
                        //tempreimg = (new Image<Bgr, byte>((int)e.FrameOut.Image.Width, (int)e.FrameOut.Image.Height, (int)e.FrameOut.Image.Width * 3, outImage.PixelDataPtr)).Clone();
                        //HOperatorSet.GenImageInterleaved(out tempreimg_H, outImage.PixelDataPtr, "bgr", (int)e.FrameOut.Image.Width, (int)e.FrameOut.Image.Height, 0, "byte", 0, 0, 0, 0, -1, 0);
                        Ptr2VisionImge(e.FrameOut.Image.Width, e.FrameOut.Image.Height, outImage.PixelDataPtr, (MyCamera.MvGvspPixelType)e.FrameOut.Image.PixelType, out OutVisionImage);
                       
                    }
                    // tempreimg = new Image<Bgr, byte>((int)e.FrameOut.Image.Width, (int)e.FrameOut.Image.Height, (int)e.FrameOut.Image.Width * 3, e.FrameOut.Image.PixelDataPtr);
                }
                //images[tupianindex]=tempreimg;
                //lasttupianindex=tupianindex;
                //tupianindex++;
                //if(tupianindex >= images.Length)
                //{
                //    tupianindex = 0;
                //}
                // PictureBox1.Image =((Image<Bgr, byte>)tempreimg).ToBitmap();
                //images.Add(tempreimg);
                //while (images.Count > 10) {
                //    images.RemoveAt(0);
                //}
                getNewImageFlag = true;

                _取图事件?.Invoke();
                tw2.Stop();
                haoshi = tw2.ElapsedMilliseconds;
                i++;
                zhenlv = i / 1.0 / tw1.ElapsedMilliseconds * 1000;
                // if(i/)
                //注意清零，
                if (tw1.ElapsedMilliseconds > 60 * 1000 || i > 10000)
                {
                    tw1.Restart();
                    i = 0;
                }
            }
            catch (Exception ex)
            {


            }
        }
        void FrameGrabThread()
        {
            IStreamGrabber streamGrabber = device.StreamGrabber;

            while (grabThreadflag)
            {
                if (m_bGrabbing)
                {
                    IFrameOut frame;

                    //ch：获取一帧图像 | en: Get one frame
                    int ret = streamGrabber.GetImageBuffer(1000, out frame);
                    if (ret != MvError.MV_OK)
                    {
                        //    Console.WriteLine("Get Image failed:{0:x8}", ret);
                        continue;
                    }
                    if (!tw1.IsRunning)
                    {
                        tw1.Restart();
                    }
                    device.ImageRender.DisplayOneFrame(PictureBox1.Handle, frame.Image);
                    i++;
                    zhenlv = i / 1.0 / tw1.ElapsedMilliseconds * 1000;
                    //ch: 释放图像缓存  | en: Release the image buffer
                    streamGrabber.FreeImageBuffer(frame);

                }
                else
                {
                    continue;
                }

            }
        }

        public bool SetSoftTrige()
        {
            reMES.Clear();
            if (CamreOpenFlag == 1 && m_bGrabbing)
            {
                //device.StreamGrabber.
                int result = device.Parameters.SetEnumValue("TriggerMode", 7);

                if (result != MvError.MV_OK)
                {
                    reMES.Add("设置相机取土模式为软触发失败");
                    return false;
                }
                else
                {
                    return true;
                }

            }
            else
            {
                reMES.Add("相机未打开");
                return false;
            }
        }

        //触发，
        public Boolean SoftTrige()
        {
            reMES.Clear();
            if (CamreOpenFlag == 1 && m_bGrabbing)
            {
                //device.StreamGrabber.
                int result = device.Parameters.SetCommandValue("TriggerSoftware");
                if (result != MvError.MV_OK)
                {
                    reMES.Add("软触发失败");
                    return false;
                }
                else
                {
                    return true;
                }

            }
            else
            {
                reMES.Add("相机未打开");
                return false;
            }
        }

        private bool IsMonoPixelFormat(MvGvspPixelType enType)
        {
            switch (enType)
            {
                case MvGvspPixelType.PixelType_Gvsp_Mono8:
                case MvGvspPixelType.PixelType_Gvsp_Mono10:
                case MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_Mono12:
                case MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
                    return true;
                default:
                    return false;
            }
        }

        private bool IsColorPixelFormat(MvGvspPixelType enType)
        {
            switch (enType)
            {
                case MvGvspPixelType.PixelType_Gvsp_RGB8_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BGR8_Packed:
                case MvGvspPixelType.PixelType_Gvsp_RGBA8_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BGRA8_Packed:
                case MvGvspPixelType.PixelType_Gvsp_YUV422_Packed:
                case MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR8:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG8:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB8:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG8:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB10:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG10:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG10:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR10:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB12:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG12:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG12:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR12:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR12_Packed:
                    return true;
                default:
                    return false;
            }
        }



        public Boolean SetExposuretime(double Exposuretime)
        {
            if (CamreOpenFlag == 1)
            {
                if (device.Parameters.SetFloatValue("ExposureTime", (float)Exposuretime) != 0)
                {
                    reMES.Add("设置曝光失败");
                    return false;
                }
                return true;
            }
            else
            {
                reMES.Add("相机未打开");
                return false;
            }

        }

        public Boolean setGain(double gain)
        {
            return true;
        }

        public void OpenCamerabyname(string name)
        {
            try
            {
                reMES.Clear();
                if (devInfoList.Count == 0)
                {
                    Enumdevlist();
                }
                int index = CameraSnNames.FindIndex(c => c.Equals(name));
                OpenCamera(index);
            }
            catch (Exception ex)
            {
                reMES.Add(ex.ToString());
            }

        }
        //关闭相机
        public void CloseCamera()
        {
            if (m_bGrabbing)
            {
                m_bGrabbing = false;
                // ch:停止抓图 || en:Stop grab image
                device.StreamGrabber.StopGrabbing();
            }
            grabThreadflag = false;
            if (device == null)
            {
                return;
            }
            int ret = device.Close();
            if (ret != MvError.MV_OK)
            {
                Console.WriteLine("Close device fail: {0}", ret);
            }
            else
            {
                Console.WriteLine("Close device success!");
            }
            device.Dispose();
            device = null;
        }
        public void SetConfig()
        {
            Frm_海康相机2 frm = new Frm_海康相机2(this);
            frm.Show();
        }
        public void LoadConfig()
        {
            if (File.Exists(Savepath))
            {
               config = XmlHelper.LoadXML<HKCaConfig>(Savepath);
            }
            if (config == null)
            {
                config = new HKCaConfig();
            }
        }
        public Boolean SaveConfig()
        {
            
            if (XmlHelper.SaveXML(Savepath, config) == "")
            {
               return true;
            }
            else
            {
               return false;
            }
        }

        /// <summary>
        /// 显示图片
        /// </summary>
        /// <param name="nHeight">高</param>
        /// <param name="nWidth">宽</param>
        /// <param name="pImageBuf">图片数据</param>
        /// <param name="enPixelType">像素格式</param>
        public bool Ptr2VisionImge(UInt32 nWidth, UInt32 nHeight, IntPtr pImageBuf, MyCamera.MvGvspPixelType enPixelType,out ICogImage outImamge)
        {
            // ch: 显示 || display
            outImamge =null;
            try
            {
               
                uint m_nRowStep = nWidth * nHeight;
                if (enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
                {
                    CogImage8Root cogImage8Root = new CogImage8Root();
                    cogImage8Root.Initialize((Int32)nWidth, (Int32)nHeight, pImageBuf, (Int32)nWidth, null);

                    CogImage8Grey cogImage8Grey = new CogImage8Grey();
                    cogImage8Grey.SetRoot(cogImage8Root);
                    outImamge = cogImage8Grey;
                    System.GC.Collect();
                }
                else
                {
                    CogImage8Root image0 = new CogImage8Root();
                    IntPtr ptr0 = new IntPtr(pImageBuf.ToInt64());
                    image0.Initialize((int)nWidth, (int)nHeight, ptr0, (int)nWidth, null);

                    CogImage8Root image1 = new CogImage8Root();
                    IntPtr ptr1 = new IntPtr(pImageBuf.ToInt64() + m_nRowStep);
                    image1.Initialize((int)nWidth, (int)nHeight, ptr1, (int)nWidth, null);

                    CogImage8Root image2 = new CogImage8Root();
                    IntPtr ptr2 = new IntPtr(pImageBuf.ToInt64() + m_nRowStep * 2);
                    image2.Initialize((int)nWidth, (int)nHeight, ptr2, (int)nWidth, null);

                    CogImage24PlanarColor colorImage = new CogImage24PlanarColor();
                    colorImage.SetRoots(image0, image1, image2);
                    outImamge = colorImage;
                    System.GC.Collect();
                }
                return true;
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return false;
            }
            return true;
        }



    }

}
